use crate::src::struct_and_type::{BloomFilter, BloomFilterHashFunc, BloomFilterValue};

extern "C" {
    fn malloc(_: u64) -> *mut ();
    fn calloc(_: u64, _: u64) -> *mut ();
    fn free(_: *mut ());
    fn memcpy(_: *mut (), _: *const (), _: u64) -> *mut ();
}
static mut salts: [u32; 64] = [
    0x1953c322 as i32 as u32,
    0x588ccf17 as i32 as u32,
    0x64bf600c as i32 as u32,
    0xa6be3f3d as u32,
    0x341a02ea as i32 as u32,
    0x15b03217 as i32 as u32,
    0x3b062858 as i32 as u32,
    0x5956fd06 as i32 as u32,
    0x18b5624f as i32 as u32,
    0xe3be0b46 as u32,
    0x20ffcd5c as i32 as u32,
    0xa35dfd2b as u32,
    0x1fc4a9bf as i32 as u32,
    0x57c45d5c as i32 as u32,
    0xa8661c4a as u32,
    0x4f1b74d2 as i32 as u32,
    0x5a6dde13 as i32 as u32,
    0x3b18dac6 as i32 as u32,
    0x5a8afbf as i32 as u32,
    0xbbda2fe2 as u32,
    0xa2520d78 as u32,
    0xe7934849 as u32,
    0xd541bc75 as u32,
    0x9a55b57 as i32 as u32,
    0x9b345ae2 as u32,
    0xfc2d26af as u32,
    0x38679cef as i32 as u32,
    0x81bd1e0d as u32,
    0x654681ae as i32 as u32,
    0x4b3d87ad as i32 as u32,
    0xd5ff10fb as u32,
    0x23b32f67 as i32 as u32,
    0xafc7e366 as u32,
    0xdd955ead as u32,
    0xe7c34b1c as u32,
    0xfeace0a6 as u32,
    0xeb16f09d as u32,
    0x3c57a72d as i32 as u32,
    0x2c8294c5 as i32 as u32,
    0xba92662a as u32,
    0xcd5b2d14 as u32,
    0x743936c8 as i32 as u32,
    0x2489beff as i32 as u32,
    0xc6c56e00 as u32,
    0x74a4f606 as i32 as u32,
    0xb244a94a as u32,
    0x5edfc423 as i32 as u32,
    0xf1901934 as u32,
    0x24af7691 as i32 as u32,
    0xf6c98b25 as u32,
    0xea25af46 as u32,
    0x76d5f2e6 as i32 as u32,
    0x5e33cdf2 as i32 as u32,
    0x445eb357 as i32 as u32,
    0x88556bd2 as u32,
    0x70d1da7a as i32 as u32,
    0x54449368 as i32 as u32,
    0x381020bc as i32 as u32,
    0x1c0520bf as i32 as u32,
    0xf7e44942 as u32,
    0xa27e2a58 as u32,
    0x66866fc5 as i32 as u32,
    0x12519ce7 as i32 as u32,
    0x437a8456 as i32 as u32,
];
#[no_mangle]
pub extern "C" fn bloom_filter_new(
    mut table_size: u32,
    mut hash_func: BloomFilterHashFunc,
    mut num_functions: u32,
) -> *mut BloomFilter {
    let mut filter: *mut BloomFilter = 0 as *mut BloomFilter;
    if num_functions as u64
        > (::core::mem::size_of::<[u32; 64]>() as u64)
            .wrapping_div(::core::mem::size_of::<u32>() as u64)
    {
        return 0 as *mut BloomFilter;
    }
    filter = (unsafe { malloc(::core::mem::size_of::<BloomFilter>() as u64) }) as *mut BloomFilter;
    if filter.is_null() {
        return 0 as *mut BloomFilter;
    }
    (unsafe {
        (*filter).table = calloc(
            table_size
                .wrapping_add(7 as i32 as u32)
                .wrapping_div(8 as i32 as u32) as u64, 1 as u64,
        ) as *mut u8
    });
    if (unsafe { (*filter).table }).is_null() {
        (unsafe { free(filter as *mut ()) });
        return 0 as *mut BloomFilter;
    }
    (unsafe { (*filter).hash_func = hash_func });
    (unsafe { (*filter).num_functions = num_functions });
    (unsafe { (*filter).table_size = table_size });
    return filter;
}
#[no_mangle]
pub extern "C" fn bloom_filter_free(mut bloomfilter: *mut BloomFilter) {
    (unsafe { free((*bloomfilter).table as *mut ()) });
    (unsafe { free(bloomfilter as *mut ()) });
}
#[no_mangle]
pub extern "C" fn bloom_filter_insert(
    mut bloomfilter: *mut BloomFilter,
    mut value: BloomFilterValue,
) {
    let mut hash: u32 = 0;
    let mut subhash: u32 = 0;
    let mut index: u32 = 0;
    let mut i: u32 = 0;
    let mut b: u8 = 0;
    hash = unsafe { ((*bloomfilter).hash_func).expect("non-null function pointer")(value) };
    i = 0 as u32;
    while i < (unsafe { (*bloomfilter).num_functions }) {
        subhash = hash ^ (unsafe { salts[i as usize] });
        index = subhash.wrapping_rem(unsafe { (*bloomfilter).table_size });
        b = ((1 as i32) << index.wrapping_rem(8 as i32 as u32)) as u8;
        let fresh0 = unsafe {
            &mut (*((*bloomfilter).table).offset(index.wrapping_div(8 as i32 as u32) as isize))
        };
        *fresh0 = (*fresh0 as i32 | b as i32) as u8;
        i = i.wrapping_add(1);
        i;
    }
}
#[no_mangle]
pub extern "C" fn bloom_filter_query(
    mut bloomfilter: *mut BloomFilter,
    mut value: BloomFilterValue,
) -> i32 {
    let mut hash: u32 = 0;
    let mut subhash: u32 = 0;
    let mut index: u32 = 0;
    let mut i: u32 = 0;
    let mut b: u8 = 0;
    let mut bit: i32 = 0;
    hash = unsafe { ((*bloomfilter).hash_func).expect("non-null function pointer")(value) };
    i = 0 as u32;
    while i < (unsafe { (*bloomfilter).num_functions }) {
        subhash = hash ^ (unsafe { salts[i as usize] });
        index = subhash.wrapping_rem(unsafe { (*bloomfilter).table_size });
        b = unsafe { *((*bloomfilter).table).offset(index.wrapping_div(8 as i32 as u32) as isize) };
        bit = (1 as i32) << index.wrapping_rem(8 as i32 as u32);
        if b as i32 & bit == 0 {
            return 0;
        }
        i = i.wrapping_add(1);
        i;
    }
    return 1;
}
#[no_mangle]
pub extern "C" fn bloom_filter_read(mut bloomfilter: *mut BloomFilter, mut array: *mut u8) {
    let mut array_size: u32 = 0;
    array_size = (unsafe { (*bloomfilter).table_size })
        .wrapping_add(7 as i32 as u32)
        .wrapping_div(8 as i32 as u32);
    (unsafe {
        memcpy(
            array as *mut (),
            (*bloomfilter).table as *const (),
            array_size as u64,
        )
    });
}
#[no_mangle]
pub extern "C" fn bloom_filter_load(mut bloomfilter: *mut BloomFilter, mut array: *mut u8) {
    let mut array_size: u32 = 0;
    array_size = (unsafe { (*bloomfilter).table_size })
        .wrapping_add(7 as i32 as u32)
        .wrapping_div(8 as i32 as u32);
    (unsafe {
        memcpy(
            (*bloomfilter).table as *mut (),
            array as *const (),
            array_size as u64,
        )
    });
}
#[no_mangle]
pub extern "C" fn bloom_filter_union(
    mut filter1: *mut BloomFilter,
    mut filter2: *mut BloomFilter,
) -> *mut BloomFilter {
    let mut result: *mut BloomFilter = 0 as *mut BloomFilter;
    let mut i: u32 = 0;
    let mut array_size: u32 = 0;
    if (unsafe { (*filter1).table_size }) != (unsafe { (*filter2).table_size })
        || (unsafe { (*filter1).num_functions }) != (unsafe { (*filter2).num_functions })
        || (unsafe { (*filter1).hash_func }) != (unsafe { (*filter2).hash_func })
    {
        return 0 as *mut BloomFilter;
    }
    result = bloom_filter_new(
        unsafe { (*filter1).table_size },
        unsafe { (*filter1).hash_func },
        unsafe { (*filter1).num_functions },
    );
    if result.is_null() {
        return 0 as *mut BloomFilter;
    }
    array_size = (unsafe { (*filter1).table_size })
        .wrapping_add(7 as i32 as u32)
        .wrapping_div(8 as i32 as u32);
    i = 0 as u32;
    while i < array_size {
        (unsafe {
            *((*result).table).offset(i as isize) = (*((*filter1).table).offset(i as isize) as i32
                | *((*filter2).table).offset(i as isize) as i32)
                as u8
        });
        i = i.wrapping_add(1);
        i;
    }
    return result;
}
#[no_mangle]
pub extern "C" fn bloom_filter_intersection(
    mut filter1: *mut BloomFilter,
    mut filter2: *mut BloomFilter,
) -> *mut BloomFilter {
    let mut result: *mut BloomFilter = 0 as *mut BloomFilter;
    let mut i: u32 = 0;
    let mut array_size: u32 = 0;
    if (unsafe { (*filter1).table_size }) != (unsafe { (*filter2).table_size })
        || (unsafe { (*filter1).num_functions }) != (unsafe { (*filter2).num_functions })
        || (unsafe { (*filter1).hash_func }) != (unsafe { (*filter2).hash_func })
    {
        return 0 as *mut BloomFilter;
    }
    result = bloom_filter_new(
        unsafe { (*filter1).table_size },
        unsafe { (*filter1).hash_func },
        unsafe { (*filter1).num_functions },
    );
    if result.is_null() {
        return 0 as *mut BloomFilter;
    }
    array_size = (unsafe { (*filter1).table_size })
        .wrapping_add(7 as i32 as u32)
        .wrapping_div(8 as i32 as u32);
    i = 0 as u32;
    while i < array_size {
        (unsafe {
            *((*result).table).offset(i as isize) = (*((*filter1).table).offset(i as isize) as i32
                & *((*filter2).table).offset(i as isize) as i32)
                as u8
        });
        i = i.wrapping_add(1);
        i;
    }
    return result;
}
